package com.hyper_yang.algorithmRecord;

public class LeetCode_48 {
//    给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
//    你必须在 原地 旋转图像，这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

    // 方法一: 数学方法--矩阵转置，翻转每一行。
    public static void rotate1(int[][] matrix) {
        int n = matrix.length; // 行数
        // 转置矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
        // 翻转每一行
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n / 2; j++) {
                int temp = matrix[i][n - j - 1];
                matrix[i][n - j - 1] = matrix[i][j];
                matrix[i][j] = temp;
            }
        }
    }

    // 方法二: 分治思想，分为四个子矩阵分别考虑
    public static void rotate2(int[][] matrix) {
        int n = matrix.length;
        // 遍历四分之一矩阵
        for (int i = 0; i < n / 2 + n % 2; i++) {
            for (int j = 0; j < n / 2; j++) {
                // 对于 matrix[i][j], 需要找到不同的四个矩阵中对应的另外三个位置和元素
                // 定义临时数组，保存对应元素
                int[] temp = new int[4];
                int row = i;
                int col = j;
                // 行列转换规律: row + newCol = n - 1, col = newRow
                for (int k = 0; k < temp.length; k++) {
                    temp[k] = matrix[row][col];
                    int x = row;
                    row = col;
                    col = n - 1 - x;
                }
                // 再次遍历要处理的四个位置，将旋转之后的数据填入
                for (int k = 0; k < temp.length; k++) {
                    // 用上一个值替换当前位置
                    matrix[row][col] = temp[(k - 1 + temp.length) % temp.length];
                    int x = row;
                    row = col;
                    col = n - 1 - x;
                }
            }
        }
    }

    // 对方法二的简单改进:
    public static void rotate(int[][] matrix) {
        int n = matrix.length;
        // 遍历四分之一矩阵
        for (int i = 0; i < (n + 1) / 2; i++) {
            for (int j = 0; j < n / 2; j++) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - j - 1][i];
                matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                matrix[j][n - i - 1] = temp;
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = new int[][]{{1, 2, 3},
                {4, 5, 6},
                {7, 8, 9}};

        int[][] matrix2 = new int[][]{{5, 1, 9, 11},
                {2, 4, 8, 10},
                {13, 3, 6, 7},
                {15, 14, 12, 16}};
        // 旋转前
        print(matrix);
        // 旋转
        rotate(matrix);
        System.out.println("==========");
        // 旋转后
        print(matrix);
    }

    public static void print(int[][] matrix) {
        for (int[] line : matrix) {
            for (int point : line) {
                System.out.print(point + "\t");
            }
            System.out.println();
        }
    }
}
